package utils

import (
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"net"
)

func UInt32ToBytes(i uint32) []byte {
	buf := make([]byte, 4)
	binary.BigEndian.PutUint32(buf, i)
	return buf
}

func UInt16ToBytes(i uint16) []byte {
	buf := make([]byte, 2)
	binary.BigEndian.PutUint16(buf, i)
	return buf
}

func Contains(s []int, e int) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

type UDPAddr struct {
	*net.UDPAddr
}

//type TCPAddr net.TCPAddr

func (addr *UDPAddr) Write(w io.Writer) {
	binary.Write(w, binary.BigEndian, addr.IP)
	port := make([]byte, 2)
	binary.BigEndian.PutUint16(port, uint16(addr.Port))
	w.Write(port)
}

func (addr *UDPAddr) Read(r io.Reader) {
	srcIP := make(net.IP, 16)
	r.Read(srcIP)
	pp := make([]byte, 2)
	r.Read(pp)
	srcPort := binary.BigEndian.Uint16(pp)
	addr.UDPAddr = &net.UDPAddr{
		IP:   srcIP,
		Port: int(srcPort),
	}
}

func (addr UDPAddr) Equal(x UDPAddr) bool {
	return addr.IP.Equal(x.IP) && addr.Port == x.Port
}

func NewUDPAddr(o *net.UDPAddr) *UDPAddr {
	addr := UDPAddr{o}
	return &addr
}

func NewUDPAddrFromAddr(o net.Addr) *UDPAddr {
	ad, err := net.ResolveUDPAddr("udp", o.String())
	if err != nil {
		log.Fatalln("NewUDPAddrFromAddr: resolve udp addr error")
	}
	addr := UDPAddr{ad}
	return &addr
}

func IsSameLanNet(addr net.Addr) bool {
	ifaces, err := net.Interfaces()
	if err != nil {
		log.Fatalln("get local Interfaces Error", err)
	}
	ar, err := net.ResolveIPAddr("ip", addr.String())
	if err != nil {
		fmt.Println(err)
		return false
	}
	for _, i := range ifaces {
		addrs, err := i.Addrs()
		if err != nil {
			log.Fatalln("get local Addrs Error", err)
		}
		for _, addr := range addrs {
			switch v := addr.(type) {
			case *net.IPNet:
				return v.Contains(ar.IP)
			case *net.IPAddr:
			}
			// process IP address
		}
	}
	return false
}
